package cn.agiledata.bank.linkbank.service;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.Map;

import cn.agiledata.bank.hibernateBean.Account;
import cn.agiledata.bank.hibernateBean.Bank;
import cn.agiledata.bank.hibernateBean.Transaction;
import cn.agiledata.bank.linkbank.exception.LinkBankException;
import cn.agiledata.bank.linkbank.form.WebPayRequestForm;
import cn.agiledata.bank.linkbank.logic.payment.UnsPayRequest;
import cn.agiledata.bank.linkbank.logic.payment.UnsPayResponse;

/**
 * 支付系统服务
 * 
 * @author maxianbo
 * 
 */
public interface WebPayService {

    /**
     * 订单时间格式
     */
    public static final String ORDER_TIME_FORMAT = "yyyyMMddHHmmss";

    /**
     * 支持直选银行的版本号
     */
    public static final String VERSION_BANK_CODE_SUPPORTED = "1.1.0";

    /**
     * 确认交易，修改交易相关状态位
     * 
     * @param transId
     *            交易编号
     * @param unsPayResponse
     *            支付系统响应
     * @throws LinkBankException
     *             如果确认过程中出现错误
     */
    public void affirmTransaction(String transId, UnsPayResponse unsPayResponse)
            throws LinkBankException;

    /**
     * 获取指定商户的密钥
     * 
     * @param accountId
     *            商户编号
     * @return 商户密钥
     */
    public String getAccountKey(String accountId);

    /**
     * 根据表示商户提交数据的Form创建Request，若Form中数据丢失则返回null
     * 
     * @param form
     *            表示商户提交数据的Form
     * @param upRequest TODO
     * @return 表示商户支付系统请求的Request
     */
    public UnsPayRequest getUnsPayRequest(WebPayRequestForm form, UnsPayRequest upRequest);

    /**
     * 根据支付系统请求获取支付系统响应Response
     * 
     * @param Request
     *            支付系统请求
     * @param requiredSave
     *            是否需要保存交易
     * @return 支付系统响应
     */
    public UnsPayResponse getUnsPayResponse(UnsPayRequest unsPayRequest,
            boolean requiredSave);

    /**
     * 保存支付系统请求对象UnsPayRequest表示的交易数据。 若可找到交易编号为指定交易编号的交易，则更新该交易； 否则创建并保存新的交易
     * 
     * @param transId
     *            交易编号
     * @param unsPayRequest
     *            支付系统请求对象
     * 
     * @return 保存后的交易对象
     */
    public Transaction saveTransaction(String transId,
            UnsPayRequest unsPayRequest);

    /**
     * 为指定UnsPayRequest设置操作类型
     * 
     * @param unsPayRequest
     *            待处理UnsPayRequest
     * @param actionTypeCode
     *            交易类型编号
     */
    public void setActionType(UnsPayRequest unsPayRequest, String actionTypeCode);

    /**
     * 验证指定客户编号是否存在且有效，如果收款子账户编号不为空，同时校验该收款子账户编号是否指定客户下的子账户
     * 
     * @param accountId
     *            客户编号
     * @param subAccountId
     *            收款子账户编号
     * @return 校验通过返回有效的客户对象
     * @throws LinkBankException
     *             若校验未通过
     */
    public Account validateAccount(String accountId, String subAccountId)
            throws LinkBankException;

    /**
     * 校验指定数字签名是否与提交的参数匹配
     * 
     * @param parameters
     *            参与校验的所有参数
     * @param mac
     *            参与比较的数字签名mac值
     * @throws LinkBankException
     *             若校验未通过
     */
    public void validateMac(Map parameters, String mac)
            throws LinkBankException;
    
    /**
     * 根据证书验签
     * 
     * @param parameters
     * 			参与校验的所有参数
     * @param sign  签名之
     * @throws LinkBankException 若校验未通过
     */
    public void validateSign(Map parameters, String sign) throws LinkBankException;

    /**
     * 验证指定客户的指定订单号的交易是否存在，只验证已经成功的交易和已付款的担保交易
     * 
     * @param accountId
     *            客户编号
     * @param orderId
     *            订单号
     * @return 可能已存在的订单的交易编号，不存在的订单返回null
     * @throws LinkBankException
     *             若校验未通过
     */
    public String validateOrderId(String accountId, String orderId)
            throws LinkBankException;

    /**
     * 根据指定交易编号查找交易并将交易数据装配到指定的WebPayRequestForm中
     * 
     * @param form
     *            待装配的WebPayRequestForm
     * @param transId
     *            交易编号
     */
    public void wireWebPayRequestForm(WebPayRequestForm form, String transId);

    /**
     * 获取系统支持的网上银行清单
     * 
     * @return 系统支持的网上银行清单
     */
    public Bank[] getSupportedNetBanks();

    /**
     * 获取系统支持的电话银行清单
     * 
     * @return 系统支持的电话银行清单
     */
    public Bank[] getSupportedTelBanks();

    /**
     * 判断指定支付系统请求的支付方式是否通过网上银行支付
     * 
     * @param unsPayRequest
     *            支付系统请求
     * @return true if 指定支付系统请求的支付方式是通过网上银行支付, otherwise false
     */
    public boolean isBankNetPayMode(UnsPayRequest unsPayRequest);

    /**
     * 判断指定支付系统请求的支付方式是否通过电话银行支付
     * 
     * @param unsPayRequest
     *            支付系统请求
     * @return true if 指定支付系统请求的支付方式是通过电话银行支付, otherwise false
     */
    public boolean isBankTelPayMode(UnsPayRequest unsPayRequest);

    /**
     * 判断指定主账户是否包含指定子账户
     * 
     * @param account
     *            主账户
     * @param subAccountId
     *            子账户编号
     * @return true if 指定主账户包含指定子账户, otherwise false
     */
    public boolean containsSubAccount(Account account, String subAccountId);

    /**
     * 判断指定版本是否支持直选银行。直选银行通过商户提供银行代码而直接跳转到网上银行页面
     * 
     * @param version
     *            版本号
     * @return true if 指定版本支持直选银行, otherwise false
     */
    public boolean isBankCodeSupported(String version);

    /**
     * 根据商户编号和订单号生成许可号
     * 
     * @param merchantId
     *            商户编号
     * @param orderId
     *            订单号
     * @return 许可号
     */
    public String generateLicense(String merchantId, String orderId);

    /**
     * 根据指定支付系统响应和反馈方式，生成mac数字签名
     * 
     * @param unsPayResponse
     *            支付系统响应
     * @param responseMode
     *            反馈方式
     * @return mac数字签名
     */
    public String generateMac(UnsPayResponse unsPayResponse, int responseMode);
    
    /**
     * 根据指定搜房支付响应和反馈方式，使用数字证书生成签名
     * 
     * @param unsPayResponse
     * @param responseMode
     * @return sign签名
     */
    public String generateSign(UnsPayResponse unsPayResponse, int responseMode);

    /**
     * 后台响应，反馈指定支付系统响应信息给商户
     * 
     * @param unsPayResponse
     *            支付系统响应
     * @throws IOException
     *             如果后台向商户反馈信息连接商户url时出现异常
     */
    public void backgroundResponse(UnsPayResponse unsPayResponse)
            throws IOException;

    /**
     * 将指定交易编号的商户交易信息从后台反馈给商户
     * 
     * @param transId
     *            交易编号
     * @throws LinkBankException
     *             如果后台向商户反馈信息连接商户url时出现异常
     */
    public void backgroundResponseByTransId(String transId)
            throws LinkBankException;

    /**
     * 将商户支付请求中商户特有的数据装配进指定交易对象中，金额等所有交易都具有的数据除外
     * 
     * @param trans
     *            交易对象
     * @param unsPayRequest
     *            商户支付请求
     */
    public void wireTransactionFormMerchant(Transaction trans,
            UnsPayRequest unsPayRequest);
    /**
     * 验证金额
     * @param amount
     * @param account
     * @param actionType
     * @throws LinkBankException
     */
    public void validateAmount(String amount) throws LinkBankException;
    /**
     * 验证费用是否大于金额
     * @param amount
     * @param account
     * @param actionType
     * @throws LinkBankException
     */
    public boolean validateFee(BigDecimal amount,Account account,String actionType);
    
    /**
     * 根据银行商户调用编号取得银行编号
     * 
     * @param linkeCode
     * @return
     */
    public String getBankCodeByLinkCode(String linkeCode);

}